fix(spec): trim dead 'delete' member from validation-rule events enum#3189
Merged
Conversation
…#3184) The rule evaluator only runs on the insert/update write path — engine.delete never invokes evaluateValidationRules — so a rule declaring events:['delete'] was a silent no-op (flagged in #3106 and the 2026-06 validation liveness audit, and actively taught by the objectstack-data skill). Guard deletions with a beforeDelete lifecycle hook instead. Narrows the enum and its hand-written mirrors in lockstep: the BaseValidationRuleShape type, objectql's BaseRule, and the metadata-protocol JSON-schema form helper (whose stale `type` enum still listing the removed unique/async/custom variants and `json`→`json_schema` is corrected in the same pass). Updates the module doc comments (delete now lives under "Deliberately NOT validation rules"), the published skill, the hand-written validation doc, and regenerates content/docs/references/data/validation.mdx. No shipped metadata declares events:['delete']; any off-spec metadata that did now fails loudly at os validate / registration instead of parsing and silently doing nothing (contract-first, PD #12). Adds a spec test asserting the rejection. Closes #3184 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VCUSMJBsX14C3RQdWFw7N7
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
📓 Docs Drift CheckThis PR changes 3 package(s): 107 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
os-zhuang
marked this pull request as ready for review
July 18, 2026 07:23
This was referenced Jul 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #3184. Follow-up to #3106 / PR #3160, which fixed the multi-row-update call-site gap and explicitly split this out.
The validation-rule
eventsenum admitted['insert', 'update', 'delete'], but the rule evaluator's runtimeModeis'insert' | 'update'andengine.deletenever invokesevaluateValidationRules— so a rule declaringevents: ['delete']silently never ran. This was flagged in #3106's "Related" section and independently bydocs/audits/2026-06-validationschema-property-liveness.md, and the publishedobjectstack-dataskill actively taught it — advertising a capability the runtime never delivers (AGENTS.md PD #10).Decision: trim, not enforce. Delete-time guards belong in
beforeDeletelifecycle hooks (already taught correctly in the skills); onlyscript/cross_fieldwould be meaningful on delete, and hooks cover that. Removing the member is contract-first (PD #12): any off-spec metadata now fails loudly atos validate/ registration instead of parsing and doing nothing.Blast radius: zero. No example app, seed, template, fixture, or test declares
events: ['delete']— the only repo-wide occurrences were doc/skill text.Changes
packages/spec/src/data/validation.zod.ts— narrow theeventsenum to['insert', 'update']; narrow theBaseValidationRuleShape.eventsmirror type; move thedeleteexplanation into the module's "Deliberately NOT validation rules" doc block (restoring the "nothing is a silent no-op" invariant).packages/objectql/src/validation/rule-validator.ts— narrow theBaseRule.eventsmirror; update the header doc comment (drops the "known gap … tracked separately" note). No evaluator logic change (the events filter already could never matchdelete).packages/metadata-protocol/src/protocol.ts— narrow the hand-written JSON-schema form-helper mirror; also correct its staletypeenum (still listed the removedunique/async/customvariants andjsoninstead ofjson_schema; "9 variants" → 6) in the same mirror-drift pass.skills/objectstack-data/rules/validation.md— remove theevents: ['delete']line; point delete guards atbeforeDeletehooks.content/docs/data-modeling/validation.mdx(hand-written table) anddocs/design/builder-ui.md(prose) — drop'delete'.content/docs/references/data/validation.mdx— regenerated (gen:schema && gen:docs)..changeset/trim-validation-delete-event.md— patch (fixed version group).Tests
packages/spec/src/data/validation.test.ts— new "events property (Validationevents: ['delete']is a silent no-op — trim it from the spec #3184)" block: accepts['insert','update'], defaults correctly, and rejects['delete']via bothScriptValidationSchemaand theValidationRuleSchemaunion entry point.Verified: spec suite 256 files / 6914 tests green, objectql suite 71 files / 936 tests green,
check:docsreports 258 generated files in sync (the check that failed on #3160), spec + metadata-protocol + objectql builds green, eslint clean.Out of scope
label/description/tags, mergecross_fieldintoscript) — separate decisions.engine.deletebehavior — unchanged; delete guards remain lifecycle-hook territory.🤖 Generated with Claude Code
https://claude.ai/code/session_01VCUSMJBsX14C3RQdWFw7N7
Generated by Claude Code